﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using MOMKeLABS.Constants;


namespace MOMKeLABS.Controls.Window
{
    public partial class Window : UserControl
    {
        /* Private variables */
        private bool isMouseCaptured { get; set; }
        private double mouseVerticalPosition { get; set; }
        private double mouseHorizontalPosition { get; set; }
        private bool isResizing { get; set; }

        public Constants.WindowConstants.WindowState State
        {
            get
            {
                return (Constants.WindowConstants.WindowState)GetValue(Window.StateProperty);
            }

            set
            {
                SetValue(Window.StateProperty, value);
            }

        }

        public Constants.WindowConstants.WindowState PreviousState
        {
            get;
            set;
        }
        
        public MinimizBarWindow MinWin { get; set; }

        private Point NormalStatePosition { get; set; }

        private Point NormalStateSize { get; set; }

        public static readonly DependencyProperty StateProperty =
            DependencyProperty.Register(
            "State", typeof(Constants.WindowConstants.WindowState),
            typeof(MOMKeLABS.Controls.Window.Window),
            new PropertyMetadata(Constants.WindowConstants.WindowState.Normal,
                new PropertyChangedCallback(OnStatePropertyChanged)));

        public static readonly DependencyProperty HeaderCaptionProperty =
            DependencyProperty.Register(
            "HeaderCaption", typeof(string),
            typeof(Window), 
                new PropertyMetadata("", 
                    new PropertyChangedCallback(OnHeaderCaptionPropertyChanged)));

        public static readonly DependencyProperty ContentElementProperty =
            DependencyProperty.Register(
            "ContentElement", typeof(UIElement),
            typeof(Window), 
                new PropertyMetadata(null,
                    new PropertyChangedCallback(OnContentElementPropertyChanged)));

        public static readonly DependencyProperty HeaderIconURLProperty =
            DependencyProperty.Register(
            "HeaderIconURL", typeof(string),
            typeof(Window), new PropertyMetadata("", new PropertyChangedCallback(OnHeaderIconURLPropertyChanged)));

        public string HeaderIconURL
        {
            get
            {
                return (string)GetValue(HeaderIconURLProperty);
            }

            set
            {
                SetValue(HeaderIconURLProperty, value);
            }
        }


        public string HeaderCaption
        {
            get
            {
                return (string)GetValue(HeaderCaptionProperty);
            }

            set
            {
                SetValue(HeaderCaptionProperty, value);
                //this.Header.TitleText = value;
            }
        }

        public UIElement ContentElement
        {
            get
            {
                return GetValue(ContentElementProperty) as Window;
            }

            set
            {
                SetValue(ContentElementProperty, value);

                // give the control a reference back to the window
                                
            }
        }

        private void SaveWindowPosition()
        {
            this.NormalStatePosition = new Point()
            {
                X = (double)this.GetValue(Canvas.LeftProperty),
                Y = (double)this.GetValue(Canvas.TopProperty)
            };

            this.NormalStateSize = new Point()
            {
                X = this.ActualWidth,
                Y = this.ActualHeight
            };
        }


        private static void OnStatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if ((App.Current as App).VisualRoot.GetType() != typeof(MainPage))
            {
                return;
            }

            MOMKeLABS.Controls.Window.Window w = (d as MOMKeLABS.Controls.Window.Window);

            if ((Constants.WindowConstants.WindowState)e.NewValue == MOMKeLABS.Constants.WindowConstants.WindowState.Maximized)
            {

                // store the information about the current window


                w.SaveWindowPosition();

                double maxHeight = (double)(w.Parent as Canvas).ActualHeight;
                double maxWidth = (double)(w.Parent as Canvas).ActualWidth;

                w.SetValue(Canvas.TopProperty, (double)0);

                w.SetValue(Canvas.LeftProperty, (double)0);

                w.Height = maxHeight;
                w.Width = maxWidth;

                ((App.Current as App).VisualRoot as MainPage).BringWindowToFront(w);

                w.PreviousState = (Constants.WindowConstants.WindowState)e.OldValue;



            }
            else if ((Constants.WindowConstants.WindowState)e.NewValue == MOMKeLABS.Constants.WindowConstants.WindowState.Minimized)
            {
                // minimize the window

                w.Visibility = Visibility.Collapsed;

                w.PreviousState = (Constants.WindowConstants.WindowState)e.OldValue;

                //(App.Current.RootVisual as MainPage).SendWindowToMinimizedBar(w);


            }
            else // set to Normal
            {


                if ((Constants.WindowConstants.WindowState)e.OldValue == WindowConstants.WindowState.Minimized)
                {
                    w.Visibility = Visibility.Visible;
                    // bring the window to the front

                    ((App.Current as App).VisualRoot as MainPage).BringWindowToFront(w);


                    return;
                }


                if (w.NormalStateSize == null || w.NormalStatePosition == null)
                {
                    return;
                }

                // restore the window to is original state

                w.Height = w.NormalStateSize.Y;
                w.Width = w.NormalStateSize.X;
                w.SetValue(Canvas.TopProperty, w.NormalStatePosition.Y);
                w.SetValue(Canvas.LeftProperty, w.NormalStatePosition.X);

                w.PreviousState = (Constants.WindowConstants.WindowState)e.OldValue;

            }
        }

        private static void OnHeaderCaptionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as MOMKeLABS.Controls.Window.Window).Header.TitleText = (string)e.NewValue;
        }

        private static void OnContentElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // call back for the property changed event
        }

        private static void OnHeaderIconURLPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as Controls.Window.Window).Header.Icon.Source = new BitmapImage(new Uri((string)e.NewValue, UriKind.Absolute));
        }

        public Window()
        {
            InitializeComponent();

            this.State = MOMKeLABS.Constants.WindowConstants.WindowState.Normal;

            this.Header.ControlBox.ParentWindow = this;

            this.DataContext = this;

            
            
            // hook up the window button control box events

            // the closing event
            this.Header.ControlBox.CloseButton.Click += new RoutedEventHandler(CloseButton_Click);

            // the window maximize event
            this.Header.ControlBox.MaximizeButton.Click += new RoutedEventHandler(MaximizeButton_Click);

            // the window minizmie event
            this.Header.ControlBox.MinimizeButton.Click += new RoutedEventHandler(MinimizeButton_Click);

            // the start resize event
            this.StatusBar.ResizeBlock.MouseLeftButtonDown += new MouseButtonEventHandler(ResizeBlock_MouseLeftButtonDown);

            // the end resize event
            this.StatusBar.ResizeBlock.MouseLeftButtonUp += new MouseButtonEventHandler(ResizeBlock_MouseLeftButtonUp);


        }

        /// <summary>
        /// do the window maximizeing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.State == MOMKeLABS.Constants.WindowConstants.WindowState.Normal)
            {
                this.State = WindowConstants.WindowState.Maximized;
            }
            else
            {
                this.State = WindowConstants.WindowState.Normal;
            }
            
        }

        /// <summary>
        /// minimize the window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MinimizeButton_Click(object sender, RoutedEventArgs e)
        {
            this.State = WindowConstants.WindowState.Minimized;
        }

        /// <summary>
        /// end the resizeing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ResizeBlock_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Header.IsDragging = false;
            isMouseCaptured = false;
            isResizing = false;
            this.ReleaseMouseCapture();
            mouseVerticalPosition = -1;
            mouseHorizontalPosition = -1;
        }

        /// <summary>
        /// start the resizeing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ResizeBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            mouseVerticalPosition = e.GetPosition(null).Y;
            mouseHorizontalPosition = e.GetPosition(null).X;
            isMouseCaptured = true;
            isResizing = true;
            this.CaptureMouse();
        }

        // here we want to close the window
        void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            if ((App.Current as App).VisualRoot.GetType() == typeof(MainPage))
            {
                ((App.Current as App).VisualRoot as MainPage).RemoveWindow(this);
            }
        }

        private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs args)
        {
            if (this.State != WindowConstants.WindowState.Normal)
                return;

            mouseVerticalPosition = args.GetPosition(null).Y;
            mouseHorizontalPosition = args.GetPosition(null).X;
            isMouseCaptured = true;

            this.CaptureMouse();
            this.Opacity = (double)App.Current.Resources["WindowDragOpacity"];
        }

        private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs args)
        {
            // This test should only fail if the window code has been used 
            // incorrectly. This will then stop the app from crashing. 
            if((App.Current as App).VisualRoot.GetType() != typeof(MainPage))
            {
                return ;
            }

            Header.IsDragging = false;
            isMouseCaptured = false;
            this.ReleaseMouseCapture();
            mouseVerticalPosition = -1;
            mouseHorizontalPosition = -1;
            this.Opacity = 1;
            this.isResizing = false;

            // make sure the window isn't parked over the top or bottom bar

            if ((double)GetValue(Canvas.TopProperty) < 0)
            {
                this.SetValue(Canvas.TopProperty, (double)0);
            }

            if((double)GetValue(Canvas.TopProperty) > (((App.Current as App).VisualRoot as MainPage).Desktop.ActualHeight - this.ActualHeight))
            {
                this.SetValue(Canvas.TopProperty, ((App.Current as App).VisualRoot as MainPage).Desktop.ActualHeight - this.ActualHeight);
            }

            // debug line
            //this.HeaderCaption = "Top: " + GetValue(Canvas.TopProperty) + " Left: " + GetValue(Canvas.LeftProperty); 

            
        }

        private void UserControl_MouseMove(object sender, MouseEventArgs args)
        {

            double deltaV, deltaH, newTop, newLeft;

            // test do the resize instead
            if (isMouseCaptured)
            {
                if (isResizing)
                {
                    // Calculate the current position of the object.
                    deltaV = args.GetPosition(null).Y - mouseVerticalPosition;
                    deltaH = args.GetPosition(null).X - mouseHorizontalPosition;

                    newTop = deltaV + (double)this.GetValue(Window.ActualHeightProperty);
                    newLeft = deltaH + (double)this.GetValue(Window.ActualWidthProperty);

                    // Set new size of object.
                    this.SetValue(Window.HeightProperty, newTop);
                    this.SetValue(Window.WidthProperty, newLeft);

                    // Update position global variables.
                    mouseVerticalPosition = args.GetPosition(null).Y;
                    mouseHorizontalPosition = args.GetPosition(null).X;
                    return;
                }  
               
                // move control based on mouse movment
                //WindowHeader item = sender as WindowHeader;


                // Calculate the current position of the object.
                deltaV = args.GetPosition(null).Y - mouseVerticalPosition;
                deltaH = args.GetPosition(null).X - mouseHorizontalPosition;
                newTop = deltaV + (double)this.GetValue(Canvas.TopProperty);
                newLeft = deltaH + (double)this.GetValue(Canvas.LeftProperty);

                // Set new position of object.
                this.SetValue(Canvas.TopProperty, newTop);
                this.SetValue(Canvas.LeftProperty, newLeft);

                // Update position global variables.
                mouseVerticalPosition = args.GetPosition(null).Y;
                mouseHorizontalPosition = args.GetPosition(null).X;
                
            }
        }

        private void UserControl_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            if ((App.Current as App).VisualRoot.GetType() == typeof(MainPage))
            {
                ((App.Current as App).VisualRoot as MainPage).BringWindowToFront(this);
            }
        }

        /// <summary>
        /// when a window loads it must add its self to the task bar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.MinWin = new MinimizBarWindow()
            {
                ImagePath = this.HeaderIconURL,
                ParentWindow = this

            };

            // we check should NEVER fail

            if ((App.Current as App).VisualRoot.GetType() == typeof(MainPage))
            {
                ((App.Current as App).VisualRoot as MainPage).MinmizeWindowContainer.Children.Add(MinWin);
            }
        }

        /// <summary>
        /// clear an open popup menus
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_MouseEnter(object sender, MouseEventArgs e)
        {

            if ((App.Current as App).VisualRoot.GetType() == typeof(MainPage))
            {

                ((App.Current as App).VisualRoot  as MainPage).CloseAllPopupWindows();
            }
        }




    }
}
